<?php

namespace App\Foundation\Utils;

use Framework\Foundation\Log\Log;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Request;
use Namshi\Cuzzle\Formatter\CurlFormatter;
use Psr\Log\LoggerInterface;
use Psr\Http\Message\RequestInterface;

class GuzzleWrap
{
    /**
     * @var LoggerInterface
     */
    public static $logger;

    public static function get($url, $header = [])
    {
        $stack = HandlerStack::create();
        $stack->push([self::class, 'stackMiddleHandler']);

        $httpClient = new Client(['handler' => $stack]);
        $response = $httpClient->get($url, [
            'verify' => false,
            'headers' => $header,
            'http_errors' => false
        ]);

        $content = (string)$response->getBody();
        $code = $response->getStatusCode();
        return [$code, $content];
    }

    public static function post($url, $data, $header = [])
    {
        $options = [
            'form_params' => $data,
            'verify' => false,
            'headers' => $header,
            'http_errors' => false
        ];

        $stack = HandlerStack::create();
        $stack->push([self::class, 'stackMiddleHandler']);

        $httpClient = new Client(['handler' => $stack]);
        $response = $httpClient->post($url, $options);

        $code = $response->getStatusCode();
        $content = (string)$response->getBody();
        return [$code, $content];
    }

    public static function postJson($url, $data, $header = [])
    {
        $options = [
            'json' => $data,
            'verify' => false,
            'headers' => $header,
            'http_errors' => false
        ];
        $stack = HandlerStack::create();
        $stack->push([self::class, 'stackMiddleHandler']);

        $httpClient = new Client(['handler' => $stack]);
        $response = $httpClient->post($url, $options);

        $code = $response->getStatusCode();
        $content = $response->getBody()->getContents();
        return [$code, $content];
    }

    public static function postBody($url, $data, $header = [])
    {
        $options = [
            'body' => $data,
            'verify' => false,
            'headers' => $header,
            'http_errors' => false
        ];
        $stack = HandlerStack::create();
        $stack->push([self::class, 'stackMiddleHandler']);

        $httpClient = new Client(['handler' => $stack]);
        $response = $httpClient->post($url, $options);

        $code = $response->getStatusCode();
        $content = $response->getBody()->getContents();
        return [$code, $content];
    }

    public static function setLogger(LoggerInterface $logger)
    {
        self::$logger = $logger;
        return self::class;
    }

    public static function stackMiddleHandler(callable $handler)
    {
        return function (RequestInterface $request, array $options) use ($handler) {
            $curlCommand = (new CurlFormatter())->format($request);

            if (!getenv("PHP_CURL_LOG_ENABLE")) {
                return $handler($request, $options);
            }
            if (getenv("PHP_CURL_LOG_URL_PATTERN") && !preg_match(getenv("PHP_CURL_LOG_URL_PATTERN"), $url)) {
                return $handler($request, $options);
            }
            if (getenv("PHP_CURL_LOG_BODY_PATTERN") && !preg_match(getenv("PHP_CURL_LOG_BODY_PATTERN"), $body)) {
                return $handler($request, $options);
            }

            if (!self::$logger instanceof LoggerInterface) {
                return $handler($request, $options);
            }

            if (!is_null(GuzzleWrap::$logger)) {
                GuzzleWrap::$logger->debug($curlCommand);
            } else {
                Log::debug($curlCommand);
            }
            return $handler($request, $options);
        };
    }
}
